﻿using ArcGisMapDesktop.Models;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

namespace ArcGisMapDesktop
{
    public partial class mian : Form
    {
        public mian()
        {
            InitializeComponent();
        }
        String homeHtml = "";
        String configMap = "";
        List<MapLayerEntity> MapUrllist = new List<MapLayerEntity>();
        private void button1_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(textBox1.Text))
            {
                MessageBox.Show("请先输入地址！");
                return;
            }
            String MobileKeystr = "";
            Dictionary<string, string> headDic = new Dictionary<string, string>();
            string urlstr = textBox1.Text + "?f=json";

            headDic["Cache-Control"] = "max-age=0";
            headDic["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8";//"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3";
            headDic["UserAgent"] = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1";
            headDic["Upgrade-Insecure-Requests"] = "1";
            configMap = BusinessRequest.GetUrl("", urlstr, headDic, MobileKeystr, Encoding.UTF8);
            ArcGisConfigEntity arcGisConfigEntity = JsonHelper.ParseFormJson<ArcGisConfigEntity>(configMap);
            if (arcGisConfigEntity == null)
            {
                MessageBox.Show("访问的地址不正确！");
                return;
            }
            else
            {
                homeHtml = BusinessRequest.GetUrl("", textBox1.Text, headDic, MobileKeystr, Encoding.UTF8);
                String[] arrystr = homeHtml.Replace("Tile Info: ", "★").Split('★');
                Regex reg = new Regex(@"(?is)<a[^>]*?href=(['""]?)(?<url>[^'""\s>]+)\1[^>]*>(?<text>(?:(?!</?a\b).)*)</a>");
                MatchCollection mc = reg.Matches(arrystr[1]);

                MapLayerEntity mapLayerEntity = null;
                Uri u = new Uri(textBox1.Text);
                int i = 0;
                foreach (Match m in mc)
                {
                    String itemurl = m.Groups["url"].Value;
                    if (itemurl.Contains(u.AbsolutePath + "/tile/"))
                    {
                        if (i % 2 == 0)
                        {
                            mapLayerEntity = new MapLayerEntity();
                        }
                        this.textBox3.Text += itemurl+ "\r\n";
                        String[] coordinates = itemurl.Replace(u.AbsolutePath + "/tile/", "").Split('/');
                        CoordinateEntity coordinateEntity = new CoordinateEntity();
                        coordinateEntity.z = int.Parse(coordinates[0]);
                        coordinateEntity.y = int.Parse(coordinates[1]);
                        coordinateEntity.x = int.Parse(coordinates[2]);
                        if (i % 2 == 0)
                        {
                            mapLayerEntity.start = coordinateEntity;
                        }
                        else
                        {
                            mapLayerEntity.end = coordinateEntity;
                            mapLayerEntity.mapLayerKey = "" + mapLayerEntity.start.x + mapLayerEntity.start.y + mapLayerEntity.start.z + mapLayerEntity.end.x + mapLayerEntity.end.y + mapLayerEntity.end.z;
                            Int32 findCount =    MapUrllist.Where(ee => ee.mapLayerKey == mapLayerEntity.mapLayerKey).Count();
                            if (findCount == 0) { 
                            MapUrllist.Add(mapLayerEntity);
                            }
                        }
                        i++;
                    }

                }

                MessageBox.Show("测试成功！");
                this.button2.Enabled = true;
                this.button4.Enabled = true;
                this.textBox1.Enabled = false;
                this.button1.Enabled = false;

            }

        }
        /// <summary>
        /// 采集队列对象
        /// </summary>
        private Queue dataQueue = new Queue();
        /// <summary>
        /// 采集队列对象
        /// </summary>
        private Queue dataQueueError = new Queue();
        private void button4_Click(object sender, EventArgs e)
        {
            this.textBox1.Enabled = true;
            this.button1.Enabled = true;
            this.button2.Enabled = false;
            this.button4.Enabled = false;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {

        }
        List<Thread>  threadList=new List<Thread>();
        String pathstr = "";
        private void button2_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(textBox4.Text)) {
                MessageBox.Show("请选择采集存放文件地址！");
                return;
            }
            if (!Directory.Exists(textBox4.Text)) {
                MessageBox.Show("采集存放文件地址有误！请检查。");
                return;
            }
            if (button2.Text == "开始采集")
            {
                this.textBox2.Text = "";
                this.textBox3.Text = "";
                threadList = new List<Thread>();
                pathstr = textBox4.Text;
                button5.Enabled = false;
                textBox1.Enabled= false;
                button1.Enabled = false;
                button4.Enabled= false;
                button3.Enabled = true;
                button2.Text = "结束采集";
                AcquisitionEntry();
            }
            else
            {
                button5.Enabled = true;
                textBox1.Enabled = true;
                button1.Enabled = true;
                button4.Enabled = true;
                button3.Enabled = false;
                button2.Text = "开始采集";
                threadList.ForEach(ee =>
                {
                    if (ee != null)
                    {
                        ee.Abort();
                    }
                });
               
            }
        }
        private Boolean isRun = false;
        /// <summary>
        /// 开始爬取
        /// </summary>
        public void AcquisitionEntry()
        {
            String filepath = textBox4.Text;
            if (!Directory.Exists(filepath))
            {
                Directory.CreateDirectory(filepath);
            }
            File.WriteAllText(pathstr+"\\configMap.json", configMap);
            logText("初始化采集任务中...\r\n");
            isRun = false;
            ///启动240线程 占用内存21.5% 内存占450mb  60个线程比较稳定
            for (int i = 0; i < 60; i++)
            {
                Thread thread = new Thread(new ThreadStart(DownloadMapImg));
                thread.Start();
                threadList.Add(thread);
            }
            label6.Text = threadList.Count.ToString();

            MapUrllist.ForEach(ee =>
            {
                    try
                    {
                         // 增加判断  设置爬取具体的地图层级
                        if (comboBox1.Text == "all" || comboBox1.Text == MapUrllist.IndexOf(ee).ToString())
                        {
                            for (int startYIndex = ee.start.y; startYIndex <= ee.end.y; startYIndex++)
                            {
                                for (int startXIndex = ee.start.x; startXIndex <= ee.end.x; startXIndex++)
                                {
                                    CoordinateEntity coordinateEntity = new CoordinateEntity();
                                    coordinateEntity.z = ee.start.z;
                                    coordinateEntity.y = startYIndex;
                                    coordinateEntity.x = startXIndex;
                                    dataQueue.Enqueue(coordinateEntity);
                                }
                            }
                            logText("开始采集...\r\n");
                           
                        }
                    }
                    catch (Exception ex)
                    {
                        logError(String.Format("初始化采集信息出错，具体错误："+ex.ToString()));
                    }
            });
          
        }
        public void DownloadMapImg()
        {
            ///判断线程已经开始运行 如果没有运行 就先休眠。
           if (dataQueue.Count < 1000) {
                Thread.Sleep(1000);
            }
            int numIndex = 0;
            while (dataQueue.Count > 0) {
                CoordinateEntity ee =(CoordinateEntity) dataQueue.Dequeue();
                if (ee != null)
                {

                    String filepath = String.Format(pathstr + "\\{0}\\{1}", ee.z, ee.y);
                    if (!Directory.Exists(filepath))
                    {
                        Directory.CreateDirectory(filepath);
                    }
                    if (!File.Exists(filepath + "\\" + ee.x + ".png"))
                    {
                        try
                        {
                            
                            var stream = BusinessRequest.DownloadUrl(textBox1.Text + String.Format("/tile/{0}/{1}/{2}", ee.z, ee.y, ee.x));
                            saveMapImg(stream, filepath + "\\" + ee.x + ".png");
                            if (numIndex % 20 == 0)
                            {
                                logText("已采集：图层" + ee.z + "层" + ee.y + "y和" + ee.x + "x地图瓦片信息\r\n");
                            }
                            numIndex++;
                        }
                        catch (Exception ex)
                        {
                            //dataQueueError.Enqueue(ee);
                            logError(String.Format("采集报错！{0}，{1}，{2}采集图层失败，具体错误信息：", ee.z, ee.y, ee.x) + ex.ToString() + "\r\n");
                        }
                    }
                }
            }
            //logText("开始发生错误的图层\r\n");
            // numIndex = 0;
            //while (dataQueueError.Count > 0)
            //{
            //    CoordinateEntity ee = (CoordinateEntity)dataQueueError.Dequeue();
            //    if (ee != null)
            //    {
            //        String filepath = String.Format(pathstr + "\\{0}\\{1}", ee.z, ee.y);
            //        if (!Directory.Exists(filepath))
            //        {
            //            Directory.CreateDirectory(filepath);
            //        }
            //        if (!File.Exists(filepath + "\\" + ee.x + ".png"))
            //        {
            //            try
            //            {
            //                var stream = BusinessRequest.DownloadUrl(textBox1.Text + String.Format("/tile/{0}/{1}/{2}", ee.z, ee.y, ee.x));
            //                saveMapImg(stream, filepath + "\\" + ee.x + ".png");
            //                if (numIndex % 20 == 0)
            //                {
            //                    logText("错误的图层采集成功：图层" + ee.z + "层" + ee.y + "y和" + ee.x + "x地图瓦片信息\r\n");
            //                }
            //                numIndex++;
            //            }
            //            catch (Exception ex)
            //            {
            //                logError(String.Format("采集报错！{0}，{1}，{2}采集图层失败，具体错误信息：", ee.z, ee.y, ee.x) + ex.ToString() + "\r\n");
            //            }
            //        }
            //    }
            //}
            logText("采集完成\r\n");
        }

        void logError(String msgstr) {
            textBox2.BeginInvoke(new Action<string>(msg =>
            {
                if (textBox2.Text.Length > 100000)
                {
                    textBox2.Text = msg;
                }
                else
                {
                    textBox2.Text += msg;
                }
                textBox2.SelectionStart = textBox2.Text.Length;
                textBox2.SelectionLength = 0;
                textBox2.ScrollToCaret();
                //webBrowser1 = new WebBrowser();
                //webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser1_DocumentCompleted);
                //webBrowser1.Navigate(dicitem.cityWWW + "/s");
            }),
                     new object[] { msgstr });

        }
       void logText(String msgstr) {
            textBox3.BeginInvoke(new Action<string>(msg =>
            {
                if (textBox3.Text.Length > 100000)
                {
                    textBox3.Text = msg;
                }
                else
                {
                    textBox3.Text += msg;
                }
                textBox3.SelectionStart = textBox3.Text.Length;
                textBox3.SelectionLength = 0;
                textBox3.ScrollToCaret();
                //webBrowser1 = new WebBrowser();
                //webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser1_DocumentCompleted);
                //webBrowser1.Navigate(dicitem.cityWWW + "/s");
            }),
                   new object[] { msgstr });
        } 
        public void saveMapImg(Stream stream,String filepath) {
         
                Bitmap bitmap = new Bitmap(stream);
                if (bitmap != null)
                {
                    bitmap.Save(filepath, ImageFormat.Png);
                }
                stream.Flush();
                stream.Close();
        }
        private void mian_Load(object sender, EventArgs e)
        {
            textBox4.Text = "G:\\testMap";
        }

        private void mian_FormClosed(object sender, FormClosedEventArgs e)
        {
            threadList.ForEach(ee =>
            {
                if (ee != null)
                {
                    ee.Abort();
                }
            });
            Application.Exit();
            Application.ExitThread();
            Environment.Exit(0);

        }

        private void button5_Click(object sender, EventArgs e)
        {
            string Path = "";
            FolderBrowserDialog folder = new FolderBrowserDialog();
            folder.Description = "选择文件所在文件夹目录";  //提示的文字
            if (folder.ShowDialog() == DialogResult.OK)
            {
                textBox4.Text = folder.SelectedPath;
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            if (threadList.Count > 500) {
                return;
            }
            for (int i = 0; i < 60; i++)
            {
                Thread thread = new Thread(new ThreadStart(DownloadMapImg));
                thread.Start();
                threadList.Add(thread);
            }
            label6.Text = threadList.Count.ToString();
        }
    }
}
